using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;
using Microsoft.OpenApi.Models;
using System.IdentityModel.Tokens.Jwt;
using System.Reflection;
using System.Text;
using Test.Api;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.

builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

#region swagger
//路径小写
builder.Services.AddRouting(options => options.LowercaseUrls = true);

builder.Services.AddSwaggerGen(options =>
{
    options.IncludeXmlComments(Path.Combine(AppContext.BaseDirectory, $"{Assembly.GetExecutingAssembly().GetName().Name}.xml"), true);

    #region 校验

    options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
    {
        Description = "Value: Bearer {token}",
        Name = "Authorization",
        In = ParameterLocation.Header,
        Type = SecuritySchemeType.ApiKey,
        Scheme = "Bearer"
    });

    options.AddSecurityRequirement(new OpenApiSecurityRequirement()
        {
          {
            new OpenApiSecurityScheme
            {
              Reference = new OpenApiReference
              {
                Type = ReferenceType.SecurityScheme,
                Id = "Bearer"
              },
              Scheme = "oauth2",
              Name = "Bearer",
              In = ParameterLocation.Header,
            },new List<string>()
          }
        });

    #endregion

});
#endregion

#region jwt

var configuration = builder.Services.BuildServiceProvider().GetRequiredService<IConfiguration>();
var tokenSection = configuration.GetSection(nameof(JwtOption));
builder.Services.Configure<JwtOption>(tokenSection);
var jwtOption = tokenSection.Get<JwtOption>();

builder.Services.AddAuthentication(options =>
{
    options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
    options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(options =>
{
    options.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters
    {
        ValidateIssuer = true,
        ValidateAudience = true,
        ValidateLifetime = true,
        ValidateIssuerSigningKey = true,
        ValidIssuer = jwtOption.Issuer,
        ValidAudience = jwtOption.Audience,
        IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtOption.SecretKey))
    };
    //验证事件
    options.Events = new JwtBearerEvents
    {
        // 在安全令牌已通过验证并生成 ClaimsIdentity 后调用
        OnTokenValidated = (context) =>
        {
            var token = context.Request.Headers["Authorization"].ToString().Trim().Replace("Bearer ", "");

            var jwtToken = (new JwtSecurityTokenHandler()).ReadJwtToken(token);

            return Task.CompletedTask;
        },
        //收到消息
        OnMessageReceived = context =>
        {
            var accessToken = context.Request.Query["access_token"];
            var path = context.HttpContext.Request.Path;

            if (!string.IsNullOrEmpty(accessToken) && (path.StartsWithSegments("/chatHub") &&
                (context.HttpContext.WebSockets.IsWebSocketRequest || context.Request.Headers["Accept"] == "text/event-stream")))
            {
                context.Token = accessToken;
            }
            return Task.CompletedTask;
        },
        //OnChallenge
        OnChallenge = context =>
        {
            //var token = context.Request.Headers["Authorization"].ToString().Trim().Replace("Bearer ", "");

            //var jwtToken = (new JwtSecurityTokenHandler()).ReadJwtToken(token);

            //context.Response.Headers.Add("Token-Error", context.ErrorDescription);

            return Task.CompletedTask;
        },
        //验证失败
        OnAuthenticationFailed = context =>
        {
            var token = context.Request.Headers["Authorization"].ToString().Trim().Replace("Bearer ", "");

            var jwtToken = (new JwtSecurityTokenHandler()).ReadJwtToken(token);

            if (jwtToken.Issuer != jwtOption.Issuer)
            {
                context.Response.Headers.Add("Token-Error-Iss", "issuer is wrong!");
            }

            if (jwtToken.Audiences.FirstOrDefault() != jwtOption.Audience)
            {
                context.Response.Headers.Add("Token-Error-Aud", "Audience is wrong!");
            }

            // 如果过期，则把<是否过期>添加到，返回头信息中
            if (context.Exception.GetType() == typeof(SecurityTokenExpiredException))
            {
                context.Response.Headers.Add("Token-Expired", "true");
            }
            return Task.CompletedTask;
        }
    };
});

#endregion

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.UseAuthorization();

app.MapControllers();

app.Run();
